import datetime
import logging
import random
import re
import time

from apscheduler.events import EVENT_JOB_ERROR
from flask import Flask
from flask_apscheduler import APScheduler
from flask_caching import Cache
from werkzeug.middleware.proxy_fix import ProxyFix
from werobot import WeRoBot
from werobot.contrib.flask import make_view

from park_service import get_boss_records, check_in_and_out_time
from util_date import DATE_FORMAT, time_delta
from utils_mail import send_alert
from yunji import login_in, is_check_out, is_check_in, query_attendance, get_daily_report, \
    review_and_evaluate_daily_report, getReportDetails, check_in

app = Flask(__name__)
scheduler = APScheduler()
scheduler.api_enabled = True
scheduler.init_app(app)
scheduler.start()
cache = Cache(config={'CACHE_TYPE': 'SimpleCache'})
cache.init_app(app)
my_robot = WeRoBot(token='xwhgame')
my_robot.config["APP_ID"] = "wxd307e24131c726dd"
my_robot.config["APP_SECRET"] = "5c88e35d98d1030a7cdba98821c5b81d"
app.add_url_rule(rule='/robot/',
                 endpoint='werobot',
                 view_func=make_view(my_robot),
                 methods=['GET', 'POST'])
client = my_robot.client
# Use the fixer
app.wsgi_app = ProxyFix(app.wsgi_app)


# 3600*4h=14400
@cache.cached(timeout=14400, key_prefix='getAccessToken')
def getAccessToken():
    token = login_in("yangkai", "aruEZ4HNa2bVEtC")
    return token


@app.route('/')
def hello():
    # client.send_text_message('oViXFt1dF-sYUylcKmZRd9Wh-eNk', '234234', kf_account=None)
    return "hello"


@my_robot.filter(re.compile(".*?boss.*?"))
def watch_boss(message):
    records = get_boss_records()
    msg = message.source + '\n'
    for k, v in records.items():
        msg += v + '\n'
    return msg

# 调试云极数联登录
# @my_robot.filter(re.compile(".*?token.*?"))
# def watch_token(message):
#     msg = getAccessToken()
#     return msg


@app.errorhandler(404)
def handle_not_found_error(error):
    return "Page not found", 404


@app.errorhandler(Exception)
def handle_generic_error(error):
    app.logger.error("An error occurred: %s", error)


@scheduler.task('cron', id='simple_report', day='*', hour='9', minute='01', misfire_grace_time=60)
def simple_report():
    #check_in(getAccessToken())
    if not is_weekday():
        return
    total_emp, unreported_list, followed_report_list = getReportDetails(getAccessToken())
    title = f"上一工作日简报{total_emp - len(unreported_list)}/{total_emp}"
    temp = ""
    if len(unreported_list) > 0:
        temp += f"未填写日报：{unreported_list}\n"
    for k, v in followed_report_list.items():
        temp = temp + f"【{k}】:\n{v}\n"
    resp_json = query_attendance(getAccessToken(), 0)
    not_check = resp_json["notCheck"]
    checked = resp_json["checked"]
    for emp in not_check:
        if emp["name"] == "赵锦花":
            temp= temp+ 'mini：未打卡\n'
            break
    for emp in checked:
        if emp["name"] == "赵锦花":
            temp= temp+ f'mini：{emp["firstCheckIn"]}\n'
            break
    send_alert(title, temp)


@scheduler.task('cron', id='is_check_out', day='*', hour='20,22', minute='0', misfire_grace_time=60)
def is_check_out_scheduler():
    is_check_out(getAccessToken())


@scheduler.task('cron', id='is_check_in', day='*', hour='8', minute='58', misfire_grace_time=60)
def is_check_in_scheduler():
    is_check_in(getAccessToken())


#评价
@scheduler.task('cron', id='review_report', day='*', hour='19-22', minute='*/5', misfire_grace_time=60)
def review_report():
    if not is_weekday():
        return
    time.sleep(random.randint(1, 50))
    list_ = get_daily_report(getAccessToken(), logDate=datetime.date.today().strftime(DATE_FORMAT),
                            memberId="7c4c52e88af1455696cd39dd5a7fbf7f")
    if len(list_) > 0:
        dict = {'9918dae36a1a4990923e16f8c95e47ac': '赵锦花', 'b42da08c2dce419fa3763d15910068a7': '赵芳芳','7199eb64e23a490684520ff3434f879b':'姜涛','68d272d28d36409690663729eb652bae':'张渊'}
        for k, v in dict.items():
            list = get_daily_report(getAccessToken(), logDate=datetime.date.today().strftime(DATE_FORMAT),
                                    memberId=k)
            if len(list) > 0:
                review_and_evaluate_daily_report(getAccessToken(), list, v)
            elif datetime.datetime.now().hour >= 22:
                send_alert("[" + v + "]未填日报", "")


@scheduler.task('cron', id='review_self_report', day='*', hour='21-23', minute='2,32', second="15",
                misfire_grace_time=60)
def review_self_report():
    if not is_weekday():
        return
    list = get_daily_report(getAccessToken(), logDate=datetime.date.today().strftime(DATE_FORMAT),
                            memberId="7c4c52e88af1455696cd39dd5a7fbf7f")
    if len(list) == 0:
        send_alert("日报填报提醒", "")


@scheduler.task('interval', id='look_up_park_info', seconds=120, misfire_grace_time=90)
def look_up_park_info():
    if cache.get('watch_dict') is None:
        return
    task_dict = cache.get('watch_dict')
    for k, v in task_dict.items():
        time_dict = check_in_and_out_time(k)
        if dict is None:
            continue
        if time_dict['InTime'] != v['InTime'] or time_dict['OutTime'] != v['OutTime']:
            v['InTime'] = time_dict['InTime']
            v['OutTime'] = time_dict['OutTime']
            task_dict[k] = v
            sub_dict = cache.get('sub_dict')
            sub_list = sub_dict[k]
            for token in sub_list:
                status = '[🔴 Down]' if len(v['InTime']) == 0 else '[✅ Up]'
                msg = f'''[{k}]{status}\nInTime:{v['InTime']}\nOutTime:{v['OutTime']}'''
                client.send_text_message(token, msg, kf_account=None)
    cache.set('watch_dict', task_dict, timeout=time_delta())


# 判断当天是否上班
def is_weekday():
    resp_json = query_attendance(getAccessToken(), 0)
    not_check = resp_json["notCheck"]
    checked = resp_json["checked"]
    return len(checked) >= len(not_check)


def watch_cph(message):
    cph = []
    if message.content == 'all':
        cph = ["晋A751MT", "晋AF98730", "晋A81031"]
    else:
        cph.append(message.content)
    sub_dict = cache.get('sub_dict')
    if sub_dict is None:
        sub_dict = {}
        cache.set('sub_dict', sub_dict, timeout=time_delta())
        cache.set('watch_dict', {}, timeout=time_delta())
    for cp in cph:
        if cp in sub_dict:
            temp_list = sub_dict[cp]
            if message.source not in temp_list:
                temp_list.append(message.source)
            sub_dict[cp] = temp_list
        else:
            temp_list = [message.source]
            sub_dict[cp] = temp_list
            time_dict = check_in_and_out_time(cp)
            status = '[🔴 Down]' if len(time_dict['InTime']) == 0 else '[✅ Up]'
            msg = f'''[{cp}]{status}\nInTime:{time_dict['InTime']}\nOutTime:{time_dict['OutTime']}'''
            client.send_text_message(message.source, msg, kf_account=None)
            watch_dict = cache.get('watch_dict')
            watch_dict[cp] = time_dict
            cache.set('watch_dict', watch_dict, timeout=time_delta())
    cache.set('sub_dict', sub_dict, timeout=time_delta())
    # return 'subscription is successful and will be notified when the status changes.'
    return str(cache.get('sub_dict')) + "\n" + str(cache.get('watch_dict'))


def error_listener(event):
    if event.exception:
        send_alert(f'The job {event.job_id} crashed :(', f'{event.traceback}: {event.exception}')
        cache.delete("getAccessToken")


my_robot.add_filter(func=watch_cph, rules=["all", re.compile(".*?晋.*?")])
scheduler.add_listener(error_listener, EVENT_JOB_ERROR)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

if __name__ != '__main__':
    gunicorn_logger = logging.getLogger('gunicorn.error')
    app.logger.handlers = gunicorn_logger.handlers
    app.logger.setLevel(gunicorn_logger.level)
